#include "graphics.h"

HRESULT gResult;

void cGraphics9::createD3D(HWND hWindow, bool windowed, bool vsync, bool zbuffer)
{

	p_mObject = Direct3DCreate9(D3D_SDK_VERSION);
	if(p_mObject == NULL)
	{
		MB("Couldn't create D3D. Please make sure that you have DirectX 9 runtime installed.");
		exit(1);
	}

	ZeroMemory(&md3dmode, sizeof(md3dmode));
	ZeroMemory(&md3dpp, sizeof(md3dpp));
	ZeroMemory(&mDefaultFontDesc, sizeof(mDefaultFontDesc));

	bWindowed = windowed;
	bVsync = vsync;
	bZbuffer = zbuffer;

	mWidth = SCREEN_WIDTH;
	mHeight = SCREEN_HEIGHT;


	if(bWindowed)
	{
		p_mObject->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &md3dmode);
		// check for 32 bit
		if(FAILED(p_mObject->CheckDeviceType(D3DADAPTER_DEFAULT,D3DDEVTYPE_HAL, md3dmode.Format, D3DFMT_A8R8G8B8, true)))
		{
			MB("Please update your video card. It is too old.");
			return;
		}
		p_mObject->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &md3dmode);

		// Setup and create window
		md3dpp.Windowed = true;
		md3dpp.hDeviceWindow = hWindow;
		md3dpp.SwapEffect = D3DSWAPEFFECT_FLIP;

		md3dpp.BackBufferFormat = md3dmode.Format;
		md3dpp.BackBufferWidth = SCREEN_WIDTH;
		md3dpp.BackBufferHeight = SCREEN_HEIGHT;

		if(FAILED(p_mObject->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWindow,
			D3DCREATE_HARDWARE_VERTEXPROCESSING,
			&md3dpp, &p_mDevice))) // no hardware vertex processing
		{
			if(FAILED(p_mObject->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWindow,
				D3DCREATE_SOFTWARE_VERTEXPROCESSING,
				&md3dpp, &p_mDevice)))
			{
				MB("Couldn't create main device");
				exit(1000);
			}
		}
	} // End windowed
	else
	{
		// Setup and create fullscreen
		md3dpp.Windowed = false;
		md3dpp.hDeviceWindow = hWindow;
		md3dpp.SwapEffect = D3DSWAPEFFECT_FLIP;

		md3dpp.BackBufferCount = 1;
		md3dpp.BackBufferFormat = D3DFMT_A8R8G8B8;
		md3dpp.BackBufferWidth = SCREEN_WIDTH;
		md3dpp.BackBufferHeight = SCREEN_HEIGHT;
		md3dpp.MultiSampleType = D3DMULTISAMPLE_NONE;
		md3dpp.MultiSampleQuality = 0;

		if(bVsync)
			md3dpp.PresentationInterval = D3DPRESENT_INTERVAL_ONE;
		else
			md3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;

		if(FAILED(p_mObject->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWindow,
			D3DCREATE_HARDWARE_VERTEXPROCESSING,
			&md3dpp, &p_mDevice)))
		{
			if(FAILED(p_mObject->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWindow,
				D3DCREATE_SOFTWARE_VERTEXPROCESSING,
				&md3dpp, &p_mDevice))) // no hardware vertex processing
			{
				MB("Couldn't create main device");
				exit(1000);
			}
		}
	} // End fullscreen


	/* for pure 2d using surfaces
	// create backbuffer surface
	gResult = p_mDevice->CreateOffscreenPlainSurface(SCREEN_WIDTH, SCREEN_HEIGHT, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &p_mBackBuffer, NULL); // 32 bit w/o alpha
	if(gResult != D3D_OK)
	MB("Couldn't create back buffer");

	// attach back buffer	// old <--
	gResult = p_mDevice->GetBackBuffer(0,0,D3DBACKBUFFER_TYPE_MONO, &p_mBackBuffer);
	if(gResult != D3D_OK)
	MB("Couldn't attach back buffer");
	*/
	
	/* for 3-d???
	D3DXMATRIX matProj;
	D3DXMatrixOrthoLH( &matProj, D3DXToRadian( 45 ), 
		mWidth / mHeight, 0.1f, 100.0f );
	p_mDevice->SetTransform( D3DTS_PROJECTION, &matProj );
	*/

	// duh
	D3DXCreateSprite(p_mDevice, &p_mSpriteHandler);

	// create default font with 24 px
	mDefaultFontDesc.Height          = 24;
	mDefaultFontDesc.Width           = 0;
	mDefaultFontDesc.Weight          = 0;
	mDefaultFontDesc.MipLevels       = 1;
	mDefaultFontDesc.Italic          = false;
	mDefaultFontDesc.CharSet         = DEFAULT_CHARSET;
	mDefaultFontDesc.OutputPrecision = OUT_DEFAULT_PRECIS;
	mDefaultFontDesc.Quality         = DEFAULT_QUALITY;
	mDefaultFontDesc.PitchAndFamily  = DEFAULT_PITCH | FF_DONTCARE;
	strcpy_s(mDefaultFontDesc.FaceName, "Arial");

	D3DXCreateFontIndirect(p_mDevice, &mDefaultFontDesc, &p_mDefaultText);
}

cGraphics9::cGraphics9()
{
	p_mObject = NULL;
	p_mDevice = NULL;
	p_mSpriteHandler = NULL;
	p_mDefaultText = NULL;
}

cGraphics9::~cGraphics9()
{
	ReleaseCOM(p_mDefaultText);
	ReleaseCOM(p_mSpriteHandler);

	ReleaseCOM(p_mDevice);

	// Always last
	ReleaseCOM(p_mObject);
}

// clears the buffer
void cGraphics9::clear(int r, int g, int b)
{
	if(p_mDevice)
	{
		if(bZbuffer)
		p_mDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(r,g,b), 1.0f, 0);
		else
			p_mDevice->Clear(0,NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(r,g,b),1.0f,0);
	}
}

// Name: beginScene
// Desc: readys the buffer for drawing. Must call before drawing
// Bugs: None
void cGraphics9::beginScene()
{
	// Begin the scene
	p_mDevice->BeginScene();
}

void cGraphics9::presentScene()
{

	// Render objects here
	p_mDevice->EndScene();
	// Present the back buffer contents to the display
	p_mDevice->Present(NULL, NULL, NULL, NULL);
}

void cGraphics9::beginSpriteDrawing()
{
	if(bZbuffer)
		p_mSpriteHandler->Begin(D3DXSPRITE_ALPHABLEND | D3DXSPRITE_SORT_DEPTH_BACKTOFRONT );
	else
		p_mSpriteHandler->Begin(D3DXSPRITE_ALPHABLEND);
}

void cGraphics9::endSpriteDrawing()
{
	p_mSpriteHandler->End();
}

// Default to white with 24 pt, Times New Roman w/o clipping
void cGraphics9::drawText(string sText, int x, int y, D3DCOLOR dColor, int height, string sFont, DWORD dFlags)
{


	RECT R = {x, y, 0, 0};
	SetRect(&R, x, y, 0, 0);
	if(height==24)
		p_mDefaultText->DrawText(p_mSpriteHandler, sText.c_str(), -1, &R, dFlags, dColor);
	else 
	{

		//---------------------------
		// make a new font with custom height
		//---------------------------

		ID3DXFont * mTempFont;
		D3DXFONT_DESC mTempDesc;

		mTempDesc.Height          = height;
		mTempDesc.Width           = 0;
		mTempDesc.Weight          = 0;
		mTempDesc.MipLevels       = 1;
		mTempDesc.Italic          = false;
		mTempDesc.CharSet         = DEFAULT_CHARSET;
		mTempDesc.OutputPrecision = OUT_DEFAULT_PRECIS;
		mTempDesc.Quality         = DEFAULT_QUALITY;
		mTempDesc.PitchAndFamily  = DEFAULT_PITCH | FF_DONTCARE;
		strcpy_s(mTempDesc.FaceName, sFont.c_str());

		D3DXCreateFontIndirect(p_mDevice, &mTempDesc, &mTempFont);

		mTempFont->DrawText(p_mSpriteHandler, sText.c_str(), -1, &R, dFlags, dColor);

		ReleaseCOM(mTempFont);
	}
}